import type { OverWrite } from '@/types';
import { UPLOAD_IMAGE_PATH } from '@/constant';
import type { RequestResult } from '@/utils/request';
import { ResponseCode } from '@/utils/request';
import {
  DeleteOutlined,
  EyeOutlined,
  LoadingOutlined,
  PlusOutlined,
} from '@ant-design/icons';
import { Image, message, notification, Space, Upload } from 'antd';
import type { RcFile, UploadProps } from 'antd/es/upload/interface';
import React, { useState } from 'react';
import StyleModule from './style.module.less';

type Props = OverWrite<
  UploadProps,
  {
    value?: string;
    onChange?: (value?: string) => void;
    uploadBoxStyle?: React.CSSProperties;
  }
>;

const SuffixList = ['.jpg', '.svg', '.jpeg', '.png'];
const FileMaxMB = 5;

const SingleUpload: React.FC<Props> = ({
  value,
  onChange,
  uploadBoxStyle,
  ...otherProps
}) => {
  const [loading, setLoading] = useState(false);

  // 用户选择文件之后，上传文件之前
  function beforeUpload(file: RcFile) {
    const { name, size } = file;

    if (SuffixList.every((suffix) => !name.includes(suffix))) {
      notification.warning({
        message: '上传文件',
        description: `只能上传${SuffixList.join(', ')}类型文件`,
      });
      return Promise.reject();
    }

    if (size > 1024 * 1024 * FileMaxMB) {
      notification.warning({
        message: '上传文件',
        description: `文件最大${FileMaxMB}M`,
      });
      return Promise.reject();
    }
    return true;
  }

  return (
    <Upload
      className={StyleModule['single-upload']}
      name="file"
      accept={SuffixList.join(',')}
      showUploadList={false}
      action={UPLOAD_IMAGE_PATH}
      beforeUpload={beforeUpload}
      onChange={({ file }) => {
        const { status, response } = file;
        switch (status) {
          case 'uploading': {
            setLoading(true);
            break;
          }
          case 'error': {
            setLoading(false);
            onChange?.(undefined);
            message.success('上传失败');
            break;
          }
          case 'done': {
            setLoading(false);
            // 超时或者未返回Body情况
            if (response) {
              const {
                code,
                data,
                message: msg,
              } = response as RequestResult<string[]>;
              if (code === ResponseCode.Success) {
                onChange?.(data?.[0]);
                message.success(msg || '上传成功');
              } else {
                onChange?.(undefined);
                message.success(msg || '上传失败');
              }
            }
            break;
          }
          default: {
            console.log(status, response);
            break;
          }
        }
      }}
      {...otherProps}
    >
      {value ? (
        <div
          className="upload-box image-box"
          style={uploadBoxStyle}
          onClick={(event) => event.stopPropagation()}
        >
          <Image
            src={value}
            alt="avatarImage"
            preview={{
              mask: (
                <Space size={8}>
                  <EyeOutlined />
                  {!otherProps.disabled && (
                    <DeleteOutlined
                      onClick={(event) => {
                        event.stopPropagation();
                        onChange?.(undefined);
                      }}
                    />
                  )}
                </Space>
              ),
            }}
            onError={() => {
              message.error('图片加载错误，请重新上传');
              onChange?.(undefined);
            }}
          />
        </div>
      ) : (
        <div className="upload-box" style={uploadBoxStyle}>
          {loading ? <LoadingOutlined /> : <PlusOutlined />}
          <div style={{ marginTop: 8 }}>上传图片</div>
        </div>
      )}
    </Upload>
  );
};

export default SingleUpload;
